<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <script src="https://cdn.jsdelivr.net/npm/vue@2.7.16/dist/vue.js"></script>
    <title>Document</title>
    <style>
      html,
      body {
        width: 100vw;
        height: 100vh;
        margin: 0 0;
        display: flex;
        justify-content: center;
        align-items: center;
      }
      canvas {
        border: 1px solid black;
      }
      .form-list {
        display: flex;
        flex-direction: column;
      }

      .arguments-intersection {
        display: flex;
      }

      .arguments-intersection-title {
        width: 131.863px;
      }
    </style>
  </head>
  <body>
    <!-- 
      已知圆心1(r1,r2)、第一个内圆半径R1、起始角θ1、终止角θ2、两个以圆心1绘制的圆的环宽都为H，飞机运动轨迹外扩12.5%，（内外都可以扩张）
      注意：这里的θ是正北坐标系角度增量，比如正北方向是0°，5°是顺时针为正增长5。
      解：
      起始角θ1<=终止角θ2，不满足交换顺序即可
      动态的θ在 [θ1,θ2] 范围内持续增长
      动态|α|= |动态的θ-起始角θ1| 
      弧长公式：L=πr|α|/180°           ==> 内缩 L=πR1|α|/180°       外扩 L=π(R1+H+H)|α|/180° 
      每次动态增量θ时，有b=H+L*12.5%    ==> 内缩 b=H+内缩L*12.5%    外扩 b=H+外扩L*12.5%     
      所求的正北坐标系扩张路线，用极坐标通用表示内外偏移路线每个离散点用(x,y)如下：
          x=r1+动态扩张的半径*cos(θ)
          y=r2+动态扩张的半径*sin(θ)
          两条路径都用极坐标公式，但其中：内缩动态扩张的半径R1-b      外扩动态扩张的半径b+2*H+R1
      
      根据以上可以按点绘制飞机两种运动轨迹
    
      ！！！注意：canvas坐标原点是左上角。y向下是正！
        canvas    正x轴为起始0°，顺时针正增长
        正北坐标系 正y轴为起始0°，顺时针正增长
      将起始角度和终止角度分别-90即是正北坐标系
     -->
    <div id="app">
      <div class="form-list">
        <div class="arguments-intersection">
          <div class="arguments-intersection-title">内圆圆心坐标:</div>
          <input v-model.number="centerCircle[0]" type="number" />
          <input v-model.number="centerCircle[1]" type="number" />
        </div>
        <div class="arguments-intersection">
          <div class="arguments-intersection-title">内圆半径:</div>
          <input v-model.number="radius" type="number" />
        </div>
        <div class="arguments-intersection">
          <div class="arguments-intersection-title">运动起始角度:</div>
          <input v-model.number="iAngle" type="number" />
          <div class="arguments-intersection-title">运动终止角度:</div>
          <input v-model.number="eAngle" type="number" />
        </div>
        <div class="arguments-intersection">
          <div class="arguments-intersection-title">环宽:</div>
          <input v-model.number="ringWidth" type="number" />
        </div>
      </div>
      <!-- <button @click="calculateIntersections">Calculate</button> -->
      <canvas ref="expansionCanvas" width="600" height="600"></canvas>
    </div>

    <script>
      const vm = new Vue({
        data() {
          return {
            centerCircle: [300, 300], // 圆心
            radius: 100, // 半径
            iAngle: 0, // 起始角度
            eAngle: 370, // 终止角度
            ringWidth: 20, // 环宽
            expansionRate: 0.125,// 偏移率
            linesObj: {
              internal_points: [], // 空数组表示没有内部点
              external_points: [], // 空数组表示没有外部点
            }, // 转弯扩张路线的点集合（内扩、外扩）
          };
        },
        methods: {
          // 根据极坐标公式计算所有外扩b点
          calculateExpansionPath(centerCircleArg, radiusArg, inceptionAngleArg, endAngleArg, ringWidthArg, expansionRate) {
            // 交换角度
            if (inceptionAngleArg > endAngleArg) {
              let temp = inceptionAngleArg;
              inceptionAngleArg = endAngleArg;
              endAngleArg = temp;
            }
            console.log(this.linesObj);

            this.linesObj.internal_points = [];
            this.linesObj.external_points = [];
            for (let addAngle = inceptionAngleArg; addAngle <= endAngleArg; addAngle += 5) {
              let alpha = Math.abs(addAngle - inceptionAngleArg);
              let arcLengthInternal = (Math.PI * radiusArg * alpha) / 180;
              let arcLengthExternal = (Math.PI * (radiusArg + ringWidthArg + ringWidthArg) * alpha) / 180;
              //   计算扩张长度b
              let bInternal = ringWidthArg + arcLengthInternal * expansionRate;
              let bExternal = ringWidthArg + arcLengthExternal * expansionRate;
              // 计算内外扩张的两个动态半径
              let innerRadius = radiusArg - bInternal;
              let outerRadius = bExternal + 2 * ringWidthArg + radiusArg;

              //   临时增量角度转为弧度
              let radian = (addAngle * Math.PI) / 180;

              // 计算外扩路线上的点
              const xOuter = centerCircleArg[0] + outerRadius * Math.cos(radian);
              const yOuter = centerCircleArg[1] + outerRadius * Math.sin(radian); //为什么是减，因为屏幕坐标左上角是原点，和直角坐标系的y轴是反的
              this.linesObj.external_points.push({ x: xOuter, y: yOuter });

              // 计算内缩路线上的点
              const xInner = centerCircleArg[0] + innerRadius * Math.cos(radian);
              const yInner = centerCircleArg[1] + innerRadius * Math.sin(radian);
              this.linesObj.internal_points.push({ x: xInner, y: yInner });
            }
            // this.internal_points = internal_points;
            // this.external_points = external_points;
          },
          drawPoints(linesPoints) {
            // TODO:
            // 获取canvas上下文
            var canvas = this.$refs.expansionCanvas;
            var ctx = canvas.getContext("2d");
            // 清除整个画布
            ctx.clearRect(0, 0, canvas.width, canvas.height);
            ctx.strokeStyle = "red";
            // 绘制内部点之间的线
            if (linesPoints.internal_points.length >= 2) {
              ctx.beginPath();
              ctx.moveTo(linesPoints.internal_points[0].x, linesPoints.internal_points[0].y);
              for (var i = 1; i < linesPoints.internal_points.length; i++) {
                ctx.lineTo(linesPoints.internal_points[i].x, linesPoints.internal_points[i].y);
              }
              ctx.stroke(); // 绘制路径
            }

            // 绘制外部点之间的线
            if (linesPoints.external_points.length >= 2) {
              ctx.beginPath();
              ctx.moveTo(linesPoints.external_points[0].x, linesPoints.external_points[0].y);
              for (var i = 1; i < linesPoints.external_points.length; i++) {
                ctx.lineTo(linesPoints.external_points[i].x, linesPoints.external_points[i].y);
              }
              ctx.stroke(); // 绘制路径
            }
          },
          drawBasicArc() {
            var canvas = this.$refs.expansionCanvas;
            var ctx = canvas.getContext("2d");
            ctx.strokeStyle = "green";
            ctx.beginPath();
            var rad1 = (this.inceptionAngle * Math.PI) / 180;
            var rad2 = (this.endAngle * Math.PI) / 180;
            ctx.arc(this.centerCircle[0], this.centerCircle[1], this.radius + this.ringWidth, rad1, rad2, false);
            ctx.stroke();
          },
          updateLines() {
            this.calculateExpansionPath(this.centerCircle, this.radius, this.inceptionAngle, this.endAngle, this.ringWidth, this.expansionRate);
            this.drawPoints(this.linesObj);
          },
        },
        computed: {
          // 将角度-90即可转为正北角度
          inceptionAngle: {
            get() {
              return this.iAngle - 90;
            },
          },
          endAngle: {
            get() {
              return this.eAngle - 90;
            },
          },
        },
        watch: {
          centerCircle: {
            // 圆心
            handler() {
              this.updateLines();
              this.drawBasicArc();
            },
          },
          radius: {
            // 半径
            handler() {
              this.updateLines();
              this.drawBasicArc();
            },
          },
          inceptionAngle: {
            // 起始角度
            handler() {
              this.updateLines();
              this.drawBasicArc();
            },
          },
          endAngle: {
            // 终止角度
            handler() {
              this.updateLines();
              this.drawBasicArc();
            },
          },
          ringWidth: {
            // 环宽
            handler() {
              this.updateLines();
              this.drawBasicArc();
            },
          },
        },
        mounted() {
          this.updateLines();
          this.drawBasicArc();
        },
      });
      vm.$mount("#app");
    </script>
  </body>
</html>
